import { io } from 'socket.io-client';
import { message as antMessage } from 'antd';

// 基础URL优先使用HTTPS，根据环境变量获取
const baseURL = process.env.REACT_APP_SOCKET_URL || 
                (window.location.protocol === 'https:' ? 
                 window.location.origin : 'http://localhost:3001');

// WebSocket连接选项
const options = {
  autoConnect: false, // 手动控制连接
  reconnection: true, // 自动重连
  reconnectionAttempts: Infinity, // 无限重连尝试
  reconnectionDelay: 1000, // 重连延迟1秒
  reconnectionDelayMax: 5000, // 最大重连延迟5秒
  timeout: 30000, // 增加连接超时
  pingTimeout: 60000, // 提高ping超时时间，避免频繁断连
  pingInterval: 25000, // 提高ping间隔
  secure: window.location.protocol === 'https:', // 在HTTPS下使用安全连接
  transports: ['websocket', 'polling'], // 支持多种传输方式，确保连接可靠性
  forceNew: false,
  query: {
    clientType: 'frontend',
    version: '1.0.0'
  }
};

// 消息队列 - 存储断线期间的消息
let messageQueue = [];
// 是否已显示重连通知
let hasShownReconnectNotice = false;
// 是否明确请求断开连接（用于避免不必要的重连）
let isDeliberateDisconnect = false;

// 创建Socket.io实例
const socket = io(baseURL, options);

// 重连状态
let isReconnecting = false;
let reconnectTimer = null;
let reconnectAttempts = 0;
let token = null;
// 页面特殊状态记录 - 用于在特定页面使用更保守的Socket策略
const sensitivePages = ['/admin/users', '/admin/settings'];
// 暂停重连状态控制
let reconnectPaused = false;

// 手动重连函数
const reconnect = () => {
  if (isReconnecting || isDeliberateDisconnect) return;
  
  // 检查是否暂停了重连
  if (reconnectPaused) {
    console.log('WebSocket重连已被暂停，稍后会恢复');
    return;
  }
  
  // 检查当前页面，如果是敏感页面，使用更保守的重连策略
  const currentPath = window.location.pathname;
  const isSensitivePage = sensitivePages.some(page => currentPath.includes(page));
  
  if (isSensitivePage) {
    console.log(`当前在敏感页面 ${currentPath}，使用保守重连策略`);
    // 使用更长的重连延迟
    reconnectAttempts = Math.max(reconnectAttempts, 3);
  }
  
  isReconnecting = true;
  reconnectAttempts++;
  
  console.log(`尝试重新连接 WebSocket (尝试 #${reconnectAttempts})...`);
  
  // 只在第一次重连时显示通知
  if (!hasShownReconnectNotice && reconnectAttempts <= 2) {
    hasShownReconnectNotice = true;
    
    // 使用较不明显的通知，避免干扰用户
    // antMessage.info('网络连接中断，正在尝试重连...', 3);
  }
  
  // 清除之前的重连定时器
  if (reconnectTimer) {
    clearTimeout(reconnectTimer);
  }
  
  // 设置重连定时器，每次尝试的延迟时间逐渐增加（最大8秒）
  const delay = Math.min(1000 * Math.pow(1.5, Math.min(reconnectAttempts, 5)), 8000);
  
  reconnectTimer = setTimeout(() => {
    if (!socket.connected && token && !reconnectPaused) {
      socket.auth = { token };
      socket.connect();
    }
    isReconnecting = false;
  }, delay);
};

// 连接WebSocket
const connectSocket = (authToken) => {
  if (!authToken) {
    console.error('WebSocket连接失败: 没有提供认证令牌');
    return null;
  }
  
  console.log('准备连接WebSocket，Token长度:', authToken.length);
  
  // 保存token以便重连使用
  token = authToken;
  
  // 断开之前的连接（如果存在）
  if (socket.connected) {
    socket.disconnect();
  }
  
  // 重置重连相关状态
  reconnectAttempts = 0;
  isReconnecting = false;
  isDeliberateDisconnect = false;
  hasShownReconnectNotice = false;
  
  // 设置授权信息 - 同时使用多种方式传递token，增加成功率
  socket.auth = { token: authToken };
  
  // 同时通过query传递token（某些环境可能更稳定）
  options.query = {
    ...options.query,
    token: authToken
  };
  
  // 使用新配置重新创建socket实例
  socket.io.opts = { ...socket.io.opts, ...options };
  
  // 确保设置好了auth信息再连接
  setTimeout(() => {
    try {
      // 连接前输出调试信息
      console.log('WebSocket连接中...');
      console.log('- 使用地址:', baseURL);
      console.log('- Token前15字符:', authToken.substring(0, 15) + '...');
      console.log('- 认证方式: auth对象 + query参数');
      
      // 连接
      socket.connect();
      
      console.log('WebSocket连接请求已发送');
    } catch (error) {
      console.error('WebSocket连接过程中出错:', error);
    }
  }, 100);
  
  // 解除之前的事件监听，避免重复监听
  socket.off('connect');
  socket.off('auth_success');
  socket.off('auth_error');
  socket.off('connect_error');
  socket.off('disconnect');
  socket.off('heartbeat');
  socket.off('reconnect');
  socket.off('reconnect_attempt');
  socket.off('reconnect_error');
  socket.off('reconnect_failed');
  
  // 监听连接事件
  socket.on('connect', () => {
    console.log('WebSocket已连接');
    reconnectAttempts = 0; // 重置重连尝试次数
    hasShownReconnectNotice = false; // 重置通知状态
    
    // 连接后立即发送认证请求
    socket.emit('auth', { token });
    
    // 如果重连成功，显示成功通知
    if (reconnectAttempts > 0) {
      // antMessage.success('网络连接已恢复', 2);
    }
    
    // 处理离线消息队列
    if (messageQueue.length > 0) {
      console.log(`处理 ${messageQueue.length} 条离线消息`);
      
      // 复制队列并清空原队列
      const queueToProcess = [...messageQueue];
      messageQueue = [];
      
      // 发送队列中的消息
      queueToProcess.forEach(({ event, data, callback }) => {
        socket.emit(event, data, callback);
      });
    }
  });
  
  // 监听认证成功事件
  socket.on('auth_success', (data) => {
    console.log('WebSocket认证成功', data);
  });
  
  // 监听认证错误事件
  socket.on('auth_error', (error) => {
    console.error('WebSocket认证失败:', error);
    // 清除无效令牌
    localStorage.removeItem('token');
    token = null; // 清除本地存储的token
    
    // 提示用户重新登录
    if (window.location.pathname !== '/login') {
      antMessage.error('登录已过期，请重新登录', 3);
      setTimeout(() => {
        window.location.href = '/login';
      }, 1500);
    }
  });
  
  // 监听连接错误事件
  socket.on('connect_error', (error) => {
    console.error('WebSocket连接错误:', error);
    
    // 如果是认证错误，可能需要重新登录
    if (error.message === 'Authentication error' || error.message === 'Authentication required') {
      // 清除无效令牌
      localStorage.removeItem('token');
      token = null; // 清除本地存储的token
      
      // 提示用户重新登录
      if (window.location.pathname !== '/login') {
        antMessage.error('登录已过期，请重新登录', 3);
        setTimeout(() => {
          window.location.href = '/login';
        }, 1500);
      }
    } else {
      // 非认证错误，触发重连机制
      reconnect();
    }
  });
  
  // 监听断开连接事件
  socket.on('disconnect', (reason) => {
    console.log('WebSocket已断开连接:', reason);
    
    // 如果是主动断开连接，不进行重连
    if (isDeliberateDisconnect) {
      console.log('用户主动断开连接，不执行重连');
      return;
    }
    
    // 根据断开原因决定是否重连
    if (reason === 'io server disconnect') {
      // 服务器主动断开，需要手动重连
      reconnect();
    } else if (reason === 'transport close' || reason === 'ping timeout' || reason === 'transport error') {
      // 网络问题导致的断开，尝试重连
      reconnect();
    }
    // Socket.IO会自动重连其他断开原因
  });
  
  // 添加自动心跳机制
  socket.on('heartbeat', () => {
    socket.emit('heartbeat-response');
  });
  
  // 添加重连成功事件处理
  socket.on('reconnect', (attemptNumber) => {
    console.log(`WebSocket重连成功，经过${attemptNumber}次尝试`);
    
    // 重新发送认证信息
    if (token) {
      socket.auth = { token }; // 确保连接选项中有正确的token
      socket.emit('auth', { token });
    }
    
    // 重置通知状态
    hasShownReconnectNotice = false;
  });
  
  // 监听重连尝试事件
  socket.on('reconnect_attempt', (attemptNumber) => {
    console.log(`WebSocket开始第${attemptNumber}次重连尝试...`);
  });
  
  // 监听重连错误事件
  socket.on('reconnect_error', (error) => {
    console.error('WebSocket重连错误:', error);
  });
  
  // 监听重连失败事件
  socket.on('reconnect_failed', () => {
    console.error('WebSocket重连失败，已达到最大尝试次数');
    // 当重连彻底失败时，显示通知
    antMessage.error('网络连接已断开，请检查网络后刷新页面', 5);
  });
  
  return socket;
};

// 断开WebSocket连接
const disconnectSocket = () => {
  isDeliberateDisconnect = true; // 标记为主动断开
  
  if (socket.connected) {
    socket.disconnect();
    console.log('WebSocket已断开连接');
  }
  
  // 清除重连定时器
  if (reconnectTimer) {
    clearTimeout(reconnectTimer);
    reconnectTimer = null;
  }
  
  token = null; // 清除token
  reconnectAttempts = 0; // 重置尝试次数
  messageQueue = []; // 清空消息队列
};

// 检查连接状态
const isConnected = () => {
  return socket.connected;
};

// 强制重连
const forceReconnect = () => {
  console.log('强制重新连接WebSocket');
  isDeliberateDisconnect = false; // 重置断开标记
  disconnectSocket();
  const savedToken = localStorage.getItem('token');
  if (savedToken) {
    return connectSocket(savedToken);
  }
  return null;
};

// 添加事件监听
const onEvent = (event, callback) => {
  socket.on(event, callback);
};

// 移除事件监听
const offEvent = (event, callback) => {
  socket.off(event, callback);
};

// 暂停重连（在敏感页面使用）
const pauseReconnect = () => {
  console.log('暂停WebSocket自动重连');
  reconnectPaused = true;
  
  if (reconnectTimer) {
    clearTimeout(reconnectTimer);
    reconnectTimer = null;
  }
  isReconnecting = false;
};

// 恢复重连
const resumeReconnect = () => {
  console.log('恢复WebSocket自动重连');
  reconnectPaused = false;
  isDeliberateDisconnect = false;
  
  // 如果当前未连接，立即尝试重连（除非在敏感页面）
  if (!socket.connected && token) {
    const currentPath = window.location.pathname;
    const isSensitivePage = sensitivePages.some(page => currentPath.includes(page));
    
    if (!isSensitivePage) {
      // 设置短暂延迟，避免快速切换导致的频繁重连
      setTimeout(() => {
        if (!socket.connected && token && !reconnectPaused) {
          reconnect();
        }
      }, 500);
    }
  }
};

// 发送事件
const emitEvent = (event, data, callback) => {
  // 避免在特定页面上频繁发送消息
  const currentPath = window.location.pathname;
  const isSensitivePage = sensitivePages.some(page => currentPath.includes(page));
  
  // 如果在敏感页面上，对非关键消息推迟发送
  if (isSensitivePage && !['auth', 'heartbeat', 'heartbeat-response'].includes(event)) {
    console.log(`当前在敏感页面 ${currentPath}，推迟发送非关键消息: ${event}`);
    
    // 将消息加入队列
    messageQueue.push({ event, data, callback });
    return false;
  }
  
  if (!socket.connected) {
    console.warn('WebSocket未连接，存入消息队列');
    
    // 存入消息队列
    messageQueue.push({ event, data, callback });
    
    // 如果未连接，尝试重连
    const savedToken = localStorage.getItem('token');
    if (savedToken && !isReconnecting && !isDeliberateDisconnect) {
      // 设置延迟重连，避免频繁重连造成负担
      setTimeout(() => {
        if (!socket.connected) {
          connectSocket(savedToken);
        }
      }, 1000);
    }
    
    return false;
  }
  
  try {
    socket.emit(event, data, callback);
    return true;
  } catch (error) {
    console.error('发送WebSocket消息失败:', error);
    
    // 发送失败时，尝试将消息加入队列
    messageQueue.push({ event, data, callback });
    return false;
  }
};

export default {
  socket,
  connectSocket,
  disconnectSocket,
  onEvent,
  offEvent,
  emitEvent,
  isConnected,
  forceReconnect,
  pauseReconnect,
  resumeReconnect
}; 